package org.sky.configuration;

import org.apache.logging.log4j.Logger;
import org.sky.security.support.CustomLoginSuccessHandler;
import org.sky.security.support.CustomLogoutHandler;
import org.sky.security.support.CustomSecurityFilter;
import org.sky.util.LogUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.sky.security.support.CustomUserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.session.ConcurrentSessionFilter;
import org.springframework.security.web.session.HttpSessionEventPublisher;
import org.springframework.security.web.session.SessionInformationExpiredStrategy;
import org.springframework.security.web.session.SimpleRedirectSessionInformationExpiredStrategy;

/**
 * @author weifx
 * @Title: WebSecurityConfig
 * @ProjectName springboot-platform
 * @Description: TODO{SpringSecurity集成}
 * @date 2019/2/28 11:21
 * @Version 1.0
 */
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    private Logger log = LogUtils.getLogger(WebSecurityConfig.class);
    @Autowired
    private CustomUserDetailsService userDetailsService;
    @Autowired
    private CustomSecurityFilter customSecurityFilter;
    @Autowired
    private CustomUserDetailsService customUserDetailsService;
    @Autowired
    private SessionRegistry sessionRegistry;
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
    @Bean
    public SessionRegistry getSessionRegistry(){
        SessionRegistry sessionRegistry=new SessionRegistryImpl();
        return sessionRegistry;
    }
    //http://localhost:8080/login 输入正确的用户名密码 并且选中remember-me 则登陆成功，转到 index页面
    //再次访问index页面无需登录直接访问
    //访问http://localhost:8080/home 不拦截，直接访问，
    //访问http://localhost:8080/hello 需要登录验证后，且具备 “ADMIN”权限hasAuthority("ADMIN")才可以访问
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        log.info("加载Security配置... ...");
        http
                .addFilterBefore(customSecurityFilter, FilterSecurityInterceptor.class)//在正确的位置添加我们自定义的过滤器
                .authorizeRequests()
                .antMatchers("/","/login","/singleLogin/**","/logout","/j_spring_security_check").permitAll()
                .anyRequest().authenticated()
                .and().sessionManagement().invalidSessionUrl("/login").maximumSessions(1).maxSessionsPreventsLogin(false).sessionRegistry(sessionRegistry)
                .and().and().formLogin()
                      .loginPage("/login")
                      .loginProcessingUrl("/j_spring_security_check")
                      .permitAll()
                      .successHandler(loginSuccessHandler())
                .and().logout().addLogoutHandler(logoutHandler()).logoutUrl("/logout").logoutSuccessUrl("/login?logout")
                .and().headers().frameOptions().sameOrigin()
                .and().csrf().disable();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        log.info("配置静态资源不进行Security拦截 ... ...");
        //解决静态资源被拦截的问题
        web.ignoring().antMatchers("/static/**");
        web.ignoring().antMatchers("/public/**");
        //解决服务注册url被拦截的问题
        web.ignoring().antMatchers("/swagger-resources/**");
        web.ignoring().antMatchers("/druid/**");
        web.ignoring().antMatchers("/v2/**");
        web.ignoring().antMatchers("/**/*.json");
        web.ignoring().antMatchers("**.js");
        //单点登录忽略Security管理,不验证session有效性
        web.ignoring().antMatchers("/singleLogin/**");
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customUserDetailsService).passwordEncoder(new PasswordEncoder(){
            @Override
            public String encode(CharSequence rawPassword) {
                //return MD5Util.encode((String)rawPassword);
                return (String)rawPassword;
            }
            @Override
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
                //return encodedPassword.equals(MD5Util.encode((String)rawPassword));
                return encodedPassword.equals(rawPassword);
            }}); //user Details Service验证
    }
    /**
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        //指定密码加密所使用的加密器为passwordEncoder()
        //需要将密码加密后写入数据库
        auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());
        //不删除凭据，以便记住用户
        auth.eraseCredentials(false);
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder(4);
    }
    **/
    /**
     * 登录成功处理
     * @return
     */
    @Bean
    public CustomLoginSuccessHandler loginSuccessHandler(){
        CustomLoginSuccessHandler loginSuccessHandler = new CustomLoginSuccessHandler();
        loginSuccessHandler.setDefaultTargetUrl("/loginSuccess");
        return loginSuccessHandler;
    }

    /**
     * 退出登录处理
     * @return
     */
    @Bean
    public CustomLogoutHandler logoutHandler(){
        return new CustomLogoutHandler();
    }

}
